import Vue from "vue";
const isServer = Vue.prototype.$isServer;

export function dateFormat(fmt, date) {
    var o = {
        "M+": date.getMonth() + 1,                 //月份
        "d+": date.getDate(),                    //日
        "H+": date.getHours(),                   //小时
        "h+": date.getHours(),                   //小时
        "m+": date.getMinutes(),                 //分
        "s+": date.getSeconds(),                 //秒
        "q+": Math.floor((date.getMonth() + 3) / 3), //季度
        "S": date.getMilliseconds()             //毫秒
    };
    if (/(y+)/.test(fmt)) {
        fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
    }
    for (var k in o) {
        if (new RegExp("(" + k + ")").test(fmt)) {
            fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
        }
    }
    return fmt;
};
// 判断参数是否是其中之一
export function oneOf(value, validList) {
  for (let i = 0; i < validList.length; i++) {
    if (value === validList[i]) {
      return true;
    }
  }
  return false;
}

export function camelcaseToHyphen(str) {
  return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
}

// For Modal scrollBar hidden
let cached;
export function getScrollBarSize(fresh) {
  if (isServer) return 0;
  if (fresh || cached === undefined) {
    const inner = document.createElement("div");
    inner.style.width = "100%";
    inner.style.height = "200px";

    const outer = document.createElement("div");
    const outerStyle = outer.style;

    outerStyle.position = "absolute";
    outerStyle.top = 0;
    outerStyle.left = 0;
    outerStyle.pointerEvents = "none";
    outerStyle.visibility = "hidden";
    outerStyle.width = "200px";
    outerStyle.height = "150px";
    outerStyle.overflow = "hidden";

    outer.appendChild(inner);

    document.body.appendChild(outer);

    const widthContained = inner.offsetWidth;
    outer.style.overflow = "scroll";
    let widthScroll = inner.offsetWidth;

    if (widthContained === widthScroll) {
      widthScroll = outer.clientWidth;
    }

    document.body.removeChild(outer);

    cached = widthContained - widthScroll;
  }
  return cached;
}

// watch DOM change
export const MutationObserver = isServer
  ? false
  : window.MutationObserver ||
    window.WebKitMutationObserver ||
    window.MozMutationObserver ||
    false;

// firstUpperCase
function firstUpperCase(str) {
  return str.toString()[0].toUpperCase() + str.toString().slice(1);
}
export { firstUpperCase };

// Warn
export function warnProp(component, prop, correctType, wrongType) {
  correctType = firstUpperCase(correctType);
  wrongType = firstUpperCase(wrongType);
    console.error(`[iView warn]: Invalid prop: type check failed for prop ${prop}. Expected ${correctType}, got ${wrongType}. (found in component: ${component})`);    // eslint-disable-line
}

function typeOf(obj) {
  const toString = Object.prototype.toString;
  const map = {
    "[object Boolean]": "boolean",
    "[object Number]": "number",
    "[object String]": "string",
    "[object Function]": "function",
    "[object Array]": "array",
    "[object Date]": "date",
    "[object RegExp]": "regExp",
    "[object Undefined]": "undefined",
    "[object Null]": "null",
    "[object Object]": "object"
  };
  return map[toString.call(obj)];
}
export { typeOf };

// deepCopy
function deepCopy(data,index,len) {
  const t = typeOf(data);
  let o;

  // 这个 if 是自己加的, 如果尝试失败，则忽略index，然后继续之前的步骤
  if(index != undefined && t === "array" && typeOf(index) === 'number'){
    if(index < 0){
      index += data.length;
    }
    if (len && typeOf(len) === 'number') {
      o = [];
      for (let i = index; i < index+len; i++) {
        o.push(deepCopy(data[i]));
      }
      return o;
    }
    else {
      if(index >= 0 && index < data.length){
        return deepCopy(data[index]);
      }
    }
  }

  if (t === "array") {
    o = [];
  } else if (t === "object") {
    o = {};
  } else {
    return data;
  }

  if (t === "array") {
    for (let i = 0; i < data.length; i++) {
      o.push(deepCopy(data[i]));
    }
  } else if (t === "object") {
    for (let i in data) {
      o[i] = deepCopy(data[i]);
    }
  }
  return o;
}
export { deepCopy };
    
/** ### 复制对象
 * #### 可： 指定或排除 指定属性
 * 例如：b = deepCopyObj(a,['a','b'],null)
 */
export function deepCopyObj(data,containPorp,removePorp) {
    if (typeOf(data) !== "object") {
        return null;
    }

    let o = {};

    for (const key in data) {
        if (data.hasOwnProperty(key)) {
            
            if(!isEmptyData(containPorp)){
                if (containPorp.includes(key)) {
                    o[key] = deepCopy(data[key]);
                }
            } else {
                if (!removePorp.includes(key)) {
                    o[key] = deepCopy(data[key]);
                }
            } 
        }
    }

    return o;
}

// null,undefined,'',{},[]  => 返回true
export function isEmptyData(val) {
    if (!val || 
        val === '' ||
        (Array.isArray(val) && val.length === 0) || 
        (Object.prototype.toString.call(val) === '[object Object]' && Object.keys(val).length === 0) ) {
        return true;
    }
    else {
        return false;
    }
}

/*
1. 主要是为了避开 直接修改props的检测
*/
export function updateObj(dst, src, delPrivate=false) {
  for(let key in src){
    dst[key] = src[key];
  }
  if (delPrivate) {
    for(let key in dst){
      if (!src[key]) {
        delete dst[key];
      }
    }
  }
}


// scrollTop animation
export function scrollTop(el, from = 0, to, duration = 500, endCallback) {
  if (!window.requestAnimationFrame) {
    window.requestAnimationFrame =
      window.webkitRequestAnimationFrame ||
      window.mozRequestAnimationFrame ||
      window.msRequestAnimationFrame ||
      function(callback) {
        return window.setTimeout(callback, 1000 / 60);
      };
  }
  const difference = Math.abs(from - to);
  const step = Math.ceil((difference / duration) * 50);

  function scroll(start, end, step) {
    if (start === end) {
      endCallback && endCallback();
      return;
    }

    let d = start + step > end ? end : start + step;
    if (start > end) {
      d = start - step < end ? end : start - step;
    }

    if (el === window) {
      window.scrollTo(d, d);
    } else {
      el.scrollTop = d;
    }
    window.requestAnimationFrame(() => scroll(d, end, step));
  }
  scroll(from, to, step);
}

// Find components upward
function findComponentUpward(context, componentName, componentNames) {
  if (typeof componentName === "string") {
    componentNames = [componentName];
  } else {
    componentNames = componentName;
  }

  let parent = context.$parent;
  let name = parent.$options.name;
  while (parent && (!name || componentNames.indexOf(name) < 0)) {
    parent = parent.$parent;
    if (parent) name = parent.$options.name;
  }
  return parent;
}
export { findComponentUpward };

// Find component downward
export function findComponentDownward(context, componentName) {
  const childrens = context.$children;
  let children = null;

  if (childrens.length) {
    for (const child of childrens) {
      const name = child.$options.name;
      if (name === componentName) {
        children = child;
        break;
      } else {
        children = findComponentDownward(child, componentName);
        if (children) break;
      }
    }
  }
  return children;
}

// Find components downward
export function findComponentsDownward(
  context,
  componentName,
  ignoreComponentNames = []
) {
  if (!Array.isArray(ignoreComponentNames)) {
    ignoreComponentNames = [ignoreComponentNames];
  }
  return context.$children.reduce((components, child) => {
    if (child.$options.name === componentName) components.push(child);
    if (ignoreComponentNames.indexOf(child.$options.name) < 0) {
      const foundChilds = findComponentsDownward(child, componentName);
      return components.concat(foundChilds);
    } else {
      return components;
    }
  }, []);
}

// Find components upward
export function findComponentsUpward(context, componentName) {
  let parents = [];
  const parent = context.$parent;
  if (parent) {
    if (parent.$options.name === componentName) parents.push(parent);
    return parents.concat(findComponentsUpward(parent, componentName));
  } else {
    return [];
  }
}

// Find brothers components
export function findBrothersComponents(
  context,
  componentName,
  exceptMe = true
) {
  let res = context.$parent.$children.filter(item => {
    return item.$options.name === componentName;
  });
  let index = res.findIndex(item => item._uid === context._uid);
  if (exceptMe) res.splice(index, 1);
  return res;
}

/* istanbul ignore next */
const trim = function(string) {
  return (string || "").replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, "");
};

/* istanbul ignore next */
export function hasClass(el, cls) {
  if (!el || !cls) return false;
  if (cls.indexOf(" ") !== -1)
    throw new Error("className should not contain space.");
  if (el.classList) {
    return el.classList.contains(cls);
  } else {
    return (" " + el.className + " ").indexOf(" " + cls + " ") > -1;
  }
}

/* istanbul ignore next */
export function addClass(el, cls) {
  if (!el) return;
  let curClass = el.className;
  const classes = (cls || "").split(" ");

  for (let i = 0, j = classes.length; i < j; i++) {
    const clsName = classes[i];
    if (!clsName) continue;

    if (el.classList) {
      el.classList.add(clsName);
    } else {
      if (!hasClass(el, clsName)) {
        curClass += " " + clsName;
      }
    }
  }
  if (!el.classList) {
    el.className = curClass;
  }
}

/* istanbul ignore next */
export function removeClass(el, cls) {
  if (!el || !cls) return;
  const classes = cls.split(" ");
  let curClass = " " + el.className + " ";

  for (let i = 0, j = classes.length; i < j; i++) {
    const clsName = classes[i];
    if (!clsName) continue;

    if (el.classList) {
      el.classList.remove(clsName);
    } else {
      if (hasClass(el, clsName)) {
        curClass = curClass.replace(" " + clsName + " ", " ");
      }
    }
  }
  if (!el.classList) {
    el.className = trim(curClass);
  }
}

export const dimensionMap = {
  xs: "480px",
  sm: "576px",
  md: "768px",
  lg: "992px",
  xl: "1200px",
  xxl: "1600px"
};

export function setMatchMedia() {
  if (typeof window !== "undefined") {
    const matchMediaPolyfill = mediaQuery => {
      return {
        media: mediaQuery,
        matches: false,
        on() {},
        off() {}
      };
    };
    window.matchMedia = window.matchMedia || matchMediaPolyfill;
  }
}

export const sharpMatcherRegx = /#([^#]+)$/;



// 获取随机 大写字符 format=[数字|小写|大写]
export function generateRandomStr(len, format) {
    len = len || 64;
    format = format || "数字"

    //
    var chars = '';
    if (format.includes('数字')) {
        chars+='1234567890'
    }
    if (format.includes('小写')) {
        chars+='abcdefjhijklmnopqrstyvwxyz'
    }
    if (format.includes('大写')) {
        chars+='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    }
    var maxPos = chars.length;
    var pwd = '';
    for (var i = 0; i < len; i++) {
        pwd += chars.charAt(Math.floor(Math.random() * maxPos));
    }
    return pwd;
}

export function generateGuid() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}
/**
 * 根据对象的属性 进行升序或者降序排序
 * 调用示例：list.sort(compare(‘属性’,'desc/不传')); 
 * @param {} pro 
 * @param {*} order 
 * @returns 
 */
export function compare(pro,order) { 
    return function (obj1, obj2) { 
        let val1 = obj1[pro]; 
        let val2 = obj2[pro]; 
        if(order=== 'desc'){undefined
            val1 =obj2[pro];
            val2 = obj1[pro]; 
        }
        if (val2 < val1 ) { //正序
            return 1; 
        } else if (val2 > val1 ) { 
            return -1; 
        } else { 
            return 0; 
        } 
    } 
} 
/**
 * 两个数组去重合并 (根据id)
 */
export function repeat(arr1,arr2){
    let json=arr1.concat(arr2);         
        let newJson = [];
        for(var i=0;i<json.length;i++){
        let flag = true;
            for(var j=0;j<newJson.length;j++){
                if(newJson[j].id==json[i].id){ 
                    flag = false;
                }
            }
            if(flag){ //判断是否重复
                newJson.push(json[i]); 
            }
        }
        arr1=newJson;
        return arr1
    
}
